﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using TechMadeira.App.UITypeEditors;
using TechMadeira.Core.Command;
using TechMadeira.Core.Logging;
using TechMadeira.Data;
using TechMadeira.Data.Commands;
using TechMadeira.Workflows;
using Factory = TechMadeira.Workflows.Factory;

namespace TechMadeira.App
{
    public partial class TechMadeiraForm : Form
    {
        public TechMadeiraForm()
        {
            InitializeComponent();

            Repository.Instance.Factory = new Factory( Repository.Instance.Factory );

            TypeDescriptor.AddAttributes( typeof(IClient), new TypeConverterAttribute(typeof(ClientTypeConverter)) );
            TypeDescriptor.AddAttributes( typeof(IClient), new EditorAttribute(typeof(ClientEditor),typeof(System.Drawing.Design.UITypeEditor)) );

            CommandManager.Instance.OnChange += m => {
                mUndoMenuItem.Enabled = m.HasUndo();
                mRedoMenuItem.Enabled = m.HasRedo();
                mUndoToolStripButton.Enabled = m.HasUndo();
                mRedoToolStripButton.Enabled = m.HasRedo();
            };

            var recorder = new CompositeRecorder();
            recorder.Append( new FileRecorder( "TechMadeira.log" ) );
            recorder.Append( new TextBoxRecorder( mLogTextBox ) );
            Logger.Instance.Recorder = new LineNumberRecorderDecorator( recorder );
        }

        private ListViewItem AppendOrder( IOrder aOrder )
        {
            var item = new ListViewItem( aOrder.Number.ToString(), 0 ) { Tag = aOrder };
            item.SubItems.Add( aOrder is IOrderWithStatus ? ( (IOrderWithStatus) aOrder ).Status : "<unknown>" );
            item.SubItems.Add( aOrder.Client != null ? aOrder.Client.Name : "<unknown>" );
            item.SubItems.Add( aOrder.Client != null ? aOrder.Client.NIF : "<unknown>" );
            item.SubItems.Add( aOrder.Date.ToShortDateString() );
            mOrdersListView.Items.Add( item );

            aOrder.OnUpdate += ( subject, data ) => {
                var order = subject as IOrder;
                item.SubItems[0].Text = order.Number.ToString();
                item.SubItems[1].Text = aOrder is IOrderWithStatus ? ((IOrderWithStatus) aOrder).Status : "<unknown>";
                item.SubItems[2].Text = order.Client != null ? aOrder.Client.Name : "<unknown>";
                item.SubItems[3].Text = order.Client != null ? order.Client.NIF   : "<unknown>";
                item.SubItems[4].Text = order.Date.ToShortDateString();
            };

            aOrder.OnUpdate += ( subject, data ) => {
                if ( ( (IOrder) subject ).Zombie ) mOrdersListView.Items.Remove( item );
                else if ( ! mOrdersListView.Items.Contains( item ) ) mOrdersListView.Items.Add( item );
            };

            return item;
        }

        private void OnNew( object sender, EventArgs e )
        {

        }

        private void OnSave( object sender, EventArgs e )
        {
            var dialog = new SaveFileDialog { Filter = @"XML Files (*.xml)|*.xml|All Files (*.*)|*.*"};
            if ( dialog.ShowDialog() == DialogResult.OK )
            {
                Repository.Instance.Save( dialog.FileName );
            }
        }
        private void OnOpen( object sender, EventArgs e )
        {
            var dialog = new OpenFileDialog { Filter = @"XML Files (*.xml)|*.xml|All Files (*.*)|*.*"};
            if ( dialog.ShowDialog() == DialogResult.OK )
            {
                mOrdersListView.Items.Clear();
                Repository.Instance.Load( dialog.FileName );

                foreach ( var semantic in Repository.Instance.Select<IOrder>() )
                {
                    AppendOrder( semantic );
                }
            }
        }

        private void OnNewOrder( object sender, EventArgs e )
        {
            var command = new CommandCreateSemantic<IOrder>();
            AppendOrder( command.Semantic as IOrder );
            CommandManager.Instance.Execute( command );            
        }

        private void OnExit( object sender, EventArgs e )
        {
            Application.Exit();
        }

        private void OnUndo( object sender, EventArgs e )
        {
            CommandManager.Instance.Undo();
        }

        private void OnRedo( object sender, EventArgs e )
        {
            CommandManager.Instance.Redo();
        }

        private void OnDeleteOrder( object sender, EventArgs e )
        {
            if ( mOrdersListView.SelectedItems.Count == 0 ) return;

            var order = mOrdersListView.SelectedItems[0].Tag as IOrder;
            if ( order == null ) return;

            CommandManager.Instance.Execute( new CommandDeleteSemantic( order ) );
        }

        private void OnSelectedOrder( object sender, EventArgs e )
        {
            if ( mOrdersListView.SelectedItems.Count == 0 ) return;

            var order = mOrdersListView.SelectedItems[0].Tag as IOrder;
            if ( order == null ) return;

            mPropertyGrid.SelectedObject = order;
        }

        private void OnWorkflowTester( object sender, EventArgs e )
        {
            var dialog = new WorkflowTester();

            if ( mOrdersListView.SelectedItems.Count > 0 )
            {
                var order = mOrdersListView.SelectedItems[ 0 ] as IOrderWithStatus;
                if ( order != null )
                {
                    dialog.State = order.State;
                }
            }

            dialog.ShowDialog();

            if ( mOrdersListView.SelectedItems.Count > 0 )
            {
                var order = mOrdersListView.SelectedItems[0].Tag as IOrderWithStatus;
                if ( order == null ) return;
                order.State = dialog.State;
            }
        }
    }
}
